<?php

namespace plugin\laoha\app\admin\controller;

use support\Request;
use plugin\admin\app\common\Util;
use plugin\admin\app\model\Role;
use plugin\admin\app\model\Rule;

Class CrudController
{
    /**
     * @var Model
     */

    protected $model = null;
    protected $builder = false;
    protected $set = [];

 
    /**
     * 无需登录及鉴权的方法
     * @var array
     */
    protected $noNeedLogin = [];

    /**
     * 需要登录无需鉴权的方法
     * @var array
     */
    protected $noNeedAuth = ['select','list','show','check'];


    //权限列表
    protected $rules = [];

    //检查私有权限，多管理员时是一个数组
    protected $private_id = 0;


    protected $dataLimit = 'personal';

    /**
     * 数据限制字段,开启私有必须指定$dataLimitField
     * user_id还是admin_id,代表了用哪个模型,用user_id则只能在前台添加记录
     */
    protected $dataLimitField = 'admin_id';


	//验证字段名称设置
	protected $validate = false;


    

	/**
	 * 审核
     * 此权限由管理权限附带
	 */
	public function check(Request $request)
	{
        if(!($this->canAccess('manage') || $this->canAccess('private'))) return json_fail('无权限');
        $data = $request->all();
        if(empty($data['ids']) && empty($data['id'])) return json_fail('操作记录未指定');
		$ids = empty($data['ids']) ? $data['id'] : $data['ids'];
        //var_export($data);
        if($this->serverBatchUpdate($ids,$data)){
            return json_ok(['data'=>[],'msg'=>'操作完成']);
        }else{
            return json_fail('操作失败');
        }	
	}	


    /**
     * 列表
     * @param $request
     */
	public function list(Request $request)
	{     
        
        $builder = $this->builder ?: $this->model;
        $this->set = $this->limitData($this->set);
		$set = array_merge($request->all(),$this->set);
		$data = laoha_query($builder,$set,$this->model);
		return json_ok($data);
	}

    /**
     * 查询
     * @param $request
     */
    public function select(Request $request)
    {      
        $builder = $this->builder ?: $this->model;   
        $this->set = $this->limitData($this->set);  
		$set = array_merge($request->all(),$this->set);
        $set['page_type']=3;	
		$data = laoha_query($builder,$set);
		return json_ok($data);
    }

	public function show(Request $request)
    {
        $type = empty($request->input('edit')) ? 'show':'edit';
        $id = $request->input('id');
		if(empty($id)){
			return json_fail('记录未指定');
		}
        if($fields = $request->input('fields')){
            $data = $this->model->select(str2arr($fields))->find($id);
        }else{
            $data = $this->model->find($id);
        }
        
        if($data){
			$data = $data->toArray();
			if(method_exists($this->model, 'out_data')){
				$data = $this->model->out_data($data,$type);
			}  			
			return json_ok($data);
		}else{
			return json_fail('记录未找到');
		}
    }


    /**
     * 新建
     * @param $id
     * @param $data
     */
    public function store(Request $request)    {
        if($this->dataLimit=='personal' && $this->dataLimitField!=='admin_id'){
            return json_fail('后台禁止添加数据');
        } 
        if($this->private_id && !$this->canAccess('private')){
            return json_fail('无私有权限');
        } 
        $data = $request->post();
		if ($this->validate && !$this->validate->scene('create')->check($data)) {
            return json_fail($this->validate->getError());
        }else{
            $password_filed = 'password';
            if (isset($data[$password_filed])) {
                $data[$password_filed] = Util::passwordHash($data[$password_filed]);
            }           
			if($this->serverStore($data)){
                return json_ok('记录新建成功');
            }else{
                return json_fail('新建失败,无权限或未知错误');
            }
		}
    }



    /**
     * 更新
     * @param $id,$ids
     * @param $data
     */
    public function update(Request $request)
    {

        $data = $request->all();
		if(isset($data['id'])){
            $password_filed = 'password';
            if (isset($data[$password_filed])) {
                // 密码为空，则不更新密码
                if ($data[$password_filed] === '') {
                    unset($data[$password_filed]);
                } else {
                    $data[$password_filed] = Util::passwordHash($data[$password_filed]);
                }
            }         
            if ($this->validate && !$this->validate->scene('update')->check($data)) {
                return json_fail($this->validate->getError());
            }   
			$id = $data['id'];
			unset($data['id']);

			if($rs = $this->serverUpdate($id,$data)){
				return json_ok($rs);
			}else{
                return json_fail('记录更新失败,出现未知错误');
            }			
		}elseif(isset($data['ids'])){
            if(!($this->canAccess('manage') || $this->canAccess('private'))){
                return json_fail('无批操作权限');
            }             
			$ids = $data['ids'];
			if($this->serverBatchUpdate($ids,$data)){
				return json_ok('记录更新成功');
			}else{
                return json_fail('记录批更新失败,出现未知错误');
            }		
		}else{
			return json_fail('未指定id');
		}
		
    }


    /**
     * 删除
     */
    public function delete(Request $request)
    {     
        $id  = $request->input('id');
        $ids = false;
		if(!$id){
            $ids = $request->input('ids');
            if($ids){
                if(!($this->canAccess('manage') || $this->canAccess('private'))){
                    return json_fail('无批操作权限');
                } 
                $id = $ids;
            }else{
                return json_fail('未指定id');
            }
        } 
        
        $data = $request->all();
        unset($data['id']);
        unset($data['ids']);
        
		if($m = $this->serverDelete($id,$data)){
			return json_ok($m.'条记录删除成功');
		}else{
			return json_fail('0条记录删除');
		}
    }

    /**
     * 不检查权限
     * @param $data
     * @return bool
     */
    protected function serverStore($data)
    { 
        $columns = getfields($this->model);
        $model   = $this->model;
        foreach ($data as $k => $v) {
            if (in_array($k, $columns)) {
				$model->setAttribute($k, $v);
            }
        }
        return $model->save();
    }    

    /** 
     * @param $primaryKey
     * @param $data
     *
     * @return bool
     */
    protected function serverUpdate($id,$ndata)
    {        
        $columns = getfields($this->model);  
        $data = $this->model->find($id);
        foreach ($ndata as $k => $v) {
            if (!in_array($k, $columns) || $k=='id') {
                continue;
            }
            $data->setAttribute($k, $v);
        }
        $data->save();
        return $data;
    }



    /**
     * 批量修改 
     */
    protected function serverBatchUpdate($id,$data)
    {  
        $columns = getfields($this->model);        

        $id=str2arr($id);       
        foreach ($data as $k => $v) {
            if (!in_array($k, $columns) || $k=='id') {
                unset($data[$k]);
            }
        }

        //返回修改记录数，此操作不触发saved等事件
        return $this->model->whereIn('id',$id)->update($data);
    }




    /**
     * @param string $ids
     *
     * @return mixed
     */
    protected function serverDelete($id)
    {        
        if(is_string($id) && strpos($id,',')){
            $id = str2arr($id);
        }
        if(is_array($id)){
            $data = $this->model->whereIn('id',$id)->get();
            $n=0;
            foreach($data as $d){
                if($d->delete()) $n++;
            }
            return $n;            
        }else{
            $data = $this->model->find($id);
            return $data->delete();
        }   

    }

    protected function limitData($set){
        if($this->dataLimit == 'personal' && $this->dataLimitField && $this->dataLimitField=='admin_id' && !($this->canAccess('manage') || $this->canAccess('private'))){
            $set[$this->dataLimitField]=admin_id();
        }
        return $set;
    }    

    //检查是否有方法权限
    protected function canAccess($name='',$admin_id=0){        
        if($name=='owner'){  //类似所有者之权
            return $this->owner($admin_id);
        }
        $rules = $this->rules ?: $this->getRules();
        if(!empty($rules['admin']) && $name!=='private'){
            return true;
        }else{
            return $rules[$name] ?? false;
        }
    }   

    
    protected function getRules(){
        $rules = $this->getAccess();
        $rules = array_fill_keys($rules, true);
        $this->rules = $rules;
        return $this->rules;
    }



    /**
     * 取权限列表
     * 返回 array
     */
    protected function getAccess(){
        $permision=[];
        if($this->private_id && $this->dataLimit=='personal' && $this->dataLimitField=='admin_id' && admin_id()==$this->private_id){
            $permision[]='private';   //私权
        }        
        if(!$this->dataLimit){  //不作权限设置
            return in_array('private',$permision) ? ['admin','private'] : ['admin'];
        }

        // 获取登录信息
        $admin = admin();
        if (!$admin) {
            return [];
        }


        // 当前管理员无角色
        $roles = $admin['roles'];
        if (!$roles) {
            return [];
        }
     
        // 角色没有规则
        $rules = Role::whereIn('id', $roles)->pluck('rules');
        $rule_ids = [];
        foreach ($rules as $rule_string) {
            if (!$rule_string) {
                continue;
            }
            $rule_ids = array_merge($rule_ids, explode(',', $rule_string));
        }
        if (!$rule_ids){
            return $permision;
        }

        // 超级管理员
        if (in_array('*', $rule_ids)){
            return in_array('private',$permision) ? ['admin','private'] : ['admin'];
        }elseif($this->dataLimit == 'personal' && in_array('#', $rule_ids)){
            return in_array('private',$permision) ? ['manage','private'] : ['manage'];
        }

        $controller = request()->controller;
        $rules = Rule::where(function ($query) use ($controller) {
            $controller_like = str_replace('\\', '\\\\', $controller);
            $query->where('key', 'like', "$controller_like@%")->orWhere('key', $controller);
        })->whereIn('id', $rule_ids)->get();
        foreach($rules as $rule){
            if($rule->key===$controller){
                $permision[]='index';
            }elseif(strpos($rule->key,"@")){
                $permision[]=substr($rule->key,strpos($rule->key,"@")-strlen($rule->key)+1);
            }
        }
        if($permision && !in_array('index',$permision)) $permision[]='index';
        $rules = array_unique($permision);
        return $rules;
    }   
        
    /**
     * 检测是否本人
     */
    protected function owner($admin_id=0){
        if($this->dataLimit=='personal' && $this->dataLimitField=='admin_id' && admin_id()===$admin_id){
            return true;
        }else{
            return false;
        }
    }
    
}
